package com.hongji.lms5xxcommunicator.grid.buff;

import com.hongji.lms5xxcommunicator.entity.ScanPointEntity;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/** 内存缓冲：基于 (ix,iy) 优先的“最新值覆盖”；flush/drain 时批量取出 */
@Component
public class InMemoryPointBuffer {
    private final ConcurrentHashMap<Long, ScanPointEntity> map = new ConcurrentHashMap<>();
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private static final double SCALE = 1000.0; // 0.001 mm 精度（仅当 ix/iy 不可用时作为兜底）

    /** 组合 key：优先 (ix,iy)；否则量化 (x,y) */
    private long keyOf(ScanPointEntity p) {
        Integer ix = p.getIx();
        Integer iy = p.getIy();
        if (ix != null && iy != null) {
            long kx = ix.longValue();
            long ky = iy.longValue();
            return (kx << 32) ^ (ky & 0xffffffffL);
        }
        // 兜底：按 (x,y) 量化
        double x = p.getX() == null ? 0 : p.getX();
        double y = p.getY() == null ? 0 : p.getY();
        long qx = Math.round(x * SCALE);
        long qy = Math.round(y * SCALE);
        return (qx << 32) ^ (qy & 0xffffffffL);
    }

    public void addOrReplace(ScanPointEntity p) {
        if (p == null) return;
        map.put(keyOf(p), p);
    }

    public void addAllOrReplace(Collection<ScanPointEntity> batch) {
        if (batch == null || batch.isEmpty()) return;
        for (ScanPointEntity p : batch) addOrReplace(p);
    }

    /** 取快照并清空（一次性落库时用） */
    public List<ScanPointEntity> snapshotAndClear() {
        lock.writeLock().lock();
        try {
            List<ScanPointEntity> out = new ArrayList<>(map.values());
            map.clear();
            return out;
        } finally {
            lock.writeLock().unlock();
        }
    }

    /** 从缓冲中拉走最多 max 条并删除（用于分批推送/周期落库） */
    public List<ScanPointEntity> drainToList(int max) {
        if (max <= 0) return Collections.emptyList();
        lock.writeLock().lock();
        try {
            int n = Math.min(max, map.size());
            if (n == 0) return Collections.emptyList();
            List<ScanPointEntity> out = new ArrayList<>(n);
            Iterator<Map.Entry<Long, ScanPointEntity>> it = map.entrySet().iterator();
            while (it.hasNext() && out.size() < n) {
                Map.Entry<Long, ScanPointEntity> e = it.next();
                out.add(e.getValue());
                it.remove(); // 边取边删
            }
            return out;
        } finally {
            lock.writeLock().unlock();
        }
    }

    public int size() { return map.size(); }
}
